package com.jojo.service;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jojo.entity.BasicInfo;
import com.jojo.entity.Result;
import com.jojo.entity.TimerInfo;
import com.jojo.mapper.BasicInfoMapper;
import com.jojo.utils.HttpClientUtil;
import com.jojo.utils.PidUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;

@Service
@Slf4j
@EnableScheduling
public class OrderService {

    @Resource
    private BasicInfoMapper basicInfoMapper;
    @Autowired
    private HttpClientUtil httpClientUtil;

    //用于执行定时任务的线程池
    private static final ExecutorService executor = ThreadUtil.newExecutor(50);
    static Map<String ,Timer> timerMap = new HashMap();
    static List<TimerInfo> timerInfoList = new ArrayList<>();

    /**
     * 一键下单
     */
    public Result oneKeySubmitOrder(HashMap<String, String> map) throws Exception {
        String phone = map.get("phone");
        String pid = map.get("pid");
        if (phone == null || "".equals(phone)) {
            return Result.build(-1, "手机号不能为空");
        }
        if (pid == null || "".equals(pid)) {
            return Result.build(-1, "商品id/链接不能为空");
        }
        QueryWrapper<BasicInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        List<BasicInfo> basicInfoList = basicInfoMapper.selectList(queryWrapper);
        if (basicInfoList.isEmpty()) {
            return Result.build(-1, "该手机号没有绑定cookie，请先绑定cookie");
        }
        String cookie = basicInfoList.get(0).getCookie();
        System.out.println("一键下单");
        return httpClientUtil.httpClient(PidUtil.parsePid(pid), cookie);
    }

    /**
     * 定时抢购
     */
    public Result timingSubmitOrder(HashMap<String, String> map) throws Exception {
        String phone = map.get("phone");
        if (phone == null || "".equals(phone)) {
            return Result.build(-1, "手机号不能为空");
        }
        String time = map.get("time");
        if (time == null || "".equals(time)) {
            return Result.build(-1, "时间不能为空");
        }
        QueryWrapper<BasicInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        List<BasicInfo> basicInfoList = basicInfoMapper.selectList(queryWrapper);
        if (basicInfoList.isEmpty()) {
            return Result.build(-1, "该手机号没有绑定cookie，请先绑定cookie");
        }
        String cookie = basicInfoList.get(0).getCookie();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        Date dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(time.replace("T", " ") + ":00");
        Date dateTimeBefore = simpleDateFormat.parse(simpleDateFormat.format(new Date(dateTime.getTime() - 100)));
        Date dateTimeAfter = simpleDateFormat.parse(simpleDateFormat.format(new Date(dateTime.getTime() + 100)));
        executor.execute(() -> {
            handelTask(dateTimeBefore, cookie,phone);
            handelTask(dateTime, cookie,phone);
            handelTask(dateTimeAfter, cookie,phone);
        });
        System.out.println("设定定时任务:"+dateTime+"；前一百毫秒："+simpleDateFormat.format(new Date(dateTime.getTime() - 100))+"；后一百毫秒："+simpleDateFormat.format(new Date(dateTime.getTime() + 100)));
        return Result.build(0, "设定成功");
    }

    /**
     * 抢购任务
     * @param dateTime 定时时间
     * @param cookie 抢购对象
     * @param phone 存储使用，不涉及抢购
     */
    public void handelTask(Date dateTime, String cookie,String phone) {
        Timer timer = new Timer();
        String timerName = timer.getClass().getName();
        TimerInfo timerInfo = setTimerInfo(timerName, phone, dateTime, false);
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
//                    ThreadUtil.execute();
                    ThreadUtil.execAsync(() -> {
                        try {
                            httpClientUtil.httpClient(cookie);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                }
//                timer.cancel();
                timerInfoList.remove(timerInfo);
                System.out.println("结束定时任务"+dateTime);
            }
        };
        timer.schedule(timerTask, dateTime);
        timerMap.put(timer.getClass().getName(),timer);

        timerInfoList.add(timerInfo);
        System.out.println("已存在定时任务数："+timerMap.size());
    }

    /**
     * 获取个人定时任务
     * @return
     */
    public List<TimerInfo> getTimeList() {
        System.out.println(timerInfoList.size());
        return timerInfoList;
    }

    /**
     * 取消定时任务
     * @param timerInfo
     * @return
     */
    public Result cancelTimer(TimerInfo timerInfo) {
        String timerName = timerInfo.getTimerName();
        Timer timer = timerMap.get(timerName);
        if (timer != null) {
            timer.cancel();
        }
        timerInfoList.remove(timerInfo);
       return Result.success(timerInfoList);
    }
    //todo 程序打包成exe个人使用，不设定账户，所有用户信息暂时保存在缓存中
    //todo 手动校验cookie
    //todo 设置自动更新cookie
    //todo 修改定时任务时间
    //todo 获取已抢购成功列表

    /**
     * 设置定时任务对象属性
     * @param timerName
     * @param phone
     * @param timerDate
     * @param isCancelTimer
     * @return
     */
    public TimerInfo setTimerInfo(String timerName,String phone,Date timerDate,Boolean isCancelTimer){
        TimerInfo timerInfo = new TimerInfo();
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
            timerInfo.setTimerName(timerName);
            timerInfo.setPhone(phone);
            timerInfo.setTimerDate(simpleDateFormat.parse(simpleDateFormat.format(timerDate)));
            timerInfo.setIsCancelTimer(isCancelTimer);
            return timerInfo;
        }catch (Exception e){
            e.printStackTrace();
        }
        return timerInfo;
    }


}
